#pragma once
#include <iostream>
using namespace std;
#include <sys/poll.h>
#include "mySock.hpp"
#include "myLog.hpp"
#define READ_EVE (0x1)
#define WRINTE_EVE (0x1 << 1)
#define EXCEPT_EVENT (0x1 << 2)
#define FD_SIZE 4096
static const uint16_t default_port = 8080;
static const int default_fd = -1;
static const uint8_t default_event = 0;
typedef struct pollfd type_t;

class PollServer
{
public:
    PollServer(uint16_t port = default_port)
        : port_(port)
    {
    }
    ~PollServer()
    {
        listenSock_.Close();
    }
    void Init()
    {
        listenSock_.Socket();
        listenSock_.Bind(port_);
        listenSock_.Listen();
        fdArray_ = new type_t[FD_SIZE];

        if (fdArray_ == nullptr)
        {
            logMessge(FATAL, "申请数组失败！ 错误码：%d 错误原因：%s", errno, strerror(errno));
            exit(NEW_ERR);
        }
        for (int i = 0; i < FD_SIZE; i++)
        {
            fdArray_[i].fd = default_fd;
            fdArray_[i].events = default_event;
            fdArray_[i].revents = default_event;
        }
    }
    void Accepter()
    {
        uint16_t CilentPort;
        string CilentIp;
        int sock = listenSock_.Accept(&CilentIp, &CilentPort);
        if (sock < 0)
        {
            logMessge(FATAL, "接受失败！ 错误码：%d 错误原因:%s", errno, strerror(errno));
            exit(ACCEPT_ERR);
        }
        int i = 1;
        for (; i < FD_SIZE; i++)
        {
            if (fdArray_[i].fd == default_fd)
                break;
        }
        if (i >= FD_SIZE)
        {
            logMessge(FATAL, "文件描述符达到上限！");
            auto fdarray = new type_t[FD_SIZE * 2];
            for (int m = 0; m < i; i++)
            {
                fdarray[m] = fdArray_[m];
            }
            delete[] fdArray_;
            fdArray_ = fdarray;
        }
        else
        {
            fdArray_[i].fd = sock;
            fdArray_[i].events = POLLIN;
            fdArray_[i].revents = default_event;
        }
    }
    void Recv(int index)
    {
        char buf[1024];
        int n = recv(fdArray_[index].fd, buf, sizeof(buf) - 1, 0);
        if (n < 0)
        {
            logMessge(FATAL, "接受消息失败！ 错误码：%d 错误原因:%s", errno, strerror(errno));
            close(fdArray_[index].fd);
        }
        else if (n == 0)
        {
            logMessge(INFO, "客户端已经关闭!");
            close(fdArray_[index].fd);

            fdArray_[index].fd = default_fd;
            fdArray_[index].events = default_event;
            fdArray_[index].revents = default_event;
        }
        else
        {
            buf[n] = 0;
            cout<<"[cilent# ]"<<buf<<endl;
            string echo = "[server echo]## ";
            echo+=buf;
            send(fdArray_[index].fd, echo.c_str(), echo.size(), 0);
        }
    }
    void Hander()
    {
        for (int i = 0; i < FD_SIZE; i++)
        {
            int fd = fdArray_[i].fd;
            short revent = fdArray_[i].revents;
            if (fd == default_fd)
                continue;
            if ((fd == listenSock_.Fd()) && ((fdArray_[i].revents & POLLIN)))
            {
                Accepter();
            }
            else if ((fd != listenSock_.Fd())&&((fdArray_[i].revents & POLLIN)))
            {
                Recv(i);
            }
            else
            {}
        }
    }
    void Start()
    {
        fdArray_[0].fd = listenSock_.Fd();
        fdArray_[0].events = POLLIN;//告诉内核我想要关心 读事件
        while (1)
        {
            int timeout = -1;//阻塞式
            int n = poll(fdArray_, FD_SIZE, timeout);
            switch (n)
            {
            case -1: //
                break;
            case 0: // 超时返回
                break;
            default: // 一个事件就绪
                logMessge(INFO, "一个文件就绪！");
                Hander();
                Print();
            }
        }
    }
    void Print()
    {
        int count = 0;
        std::cout << "fdArray_[]: ";
        for (; count < FD_SIZE; count++)
        {
            if (fdArray_[count].fd == default_fd)
                continue;
            cout << fdArray_[count].fd << " ";
        }
        cout << endl;
    }

private:
    uint16_t port_;
    Sock listenSock_;
    type_t *fdArray_;
};